<template>
  <div class="topologyLineEdit">
    <el-drawer v-model="drawer" v-if="drawer" :size="576">
      <template #header>
        <h4>对象</h4>
      </template>
      <template #default>
        <el-form
          :model="form"
          :rules="rules"
          ref="ruleFormRef"
          label-width="120px"
          label-position="top"
        >
          <el-form-item>
            <el-radio-group
              v-model="objType"
              :disabled="!isAdd"
              @input="handleTypeChange"
            >
              <el-radio-button label="1">实体</el-radio-button>
              <el-radio-button label="2">事件</el-radio-button>
            </el-radio-group>
          </el-form-item>
          <el-form-item label="对象类型名称" prop="name">
            <el-input v-model="form.name" />
          </el-form-item>
          <el-form-item label="Icon">
            <div class="iconBox" :style="{ height: isMore ? '108px' : '74px' }">
              <div class="left-chooice">
                <div
                  class="show-selection"
                  :style="{ backgroundColor: iconColor }"
                >
                  <i class="iconfont" :class="iconText"></i>
                </div>
              </div>
              <div class="right">
                <div class="up-color">
                  <span
                    class="circle pointer"
                    v-for="circleColor in colorList"
                    :key="circleColor"
                    :class="iconColor === circleColor ? 'activate' : ''"
                  >
                    <span
                      class="color"
                      :style="{ backgroundColor: circleColor }"
                      @click="handleColorChoose(circleColor)"
                    ></span>
                  </span>
                </div>
                <div class="down-icon">
                  <div class="icon-wapper" style="width: 310px">
                    <div
                      class="wrapper"
                      :class="iconText ? '' : 'activate'"
                      @click="handleClearIcon"
                    >
                      <i class="iconfont icon_forbid_fill"></i>
                    </div>
                    <div
                      class="wrapper"
                      v-for="icon in realIconList"
                      :key="icon"
                      :class="iconText === icon ? 'activate' : ''"
                    >
                      <i
                        class="iconfont"
                        :class="icon"
                        @click="handleIconChoose(icon)"
                      ></i>
                    </div>
                    <div
                      class="collapseIcon cursor-pointer"
                      style="padding: 4px 10px"
                      @click="showMoreIcon"
                    >
                      {{ isMore ? "收起" : "更多" }}
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </el-form-item>
          <el-form-item label="属性">
            <el-table
              :data="form.propTable"
              style="width: 100%"
              max-height="300"
              :row-class-name="tableRowClassName"
              ref="editTable"
            >
              <el-table-column label="属性名称" prop="name">
                <template v-slot="{ row, $index }">
                  <span v-if="!row.isEdit">{{ row.name }}</span>
                  <el-form-item
                    v-if="row.isEdit"
                    :prop="'propTable.' + $index + '.name'"
                    :key="$index"
                    :rules="[
                      {
                        validator: checkName,
                        trigger: 'change',
                      },
                    ]"
                  >
                    <el-input
                      type="text"
                      placeholder="请输入属性名"
                      v-model="row.name"
                    ></el-input>
                  </el-form-item>
                </template>
              </el-table-column>
              <el-table-column label="数据类型" prop="dataType">
                <template v-slot="{ row }">
                  <span v-show="!row.isEdit">{{ row.dataType }}</span>
                  <el-select
                    v-show="row.isEdit"
                    v-model="row.dataType"
                    :disabled="row.code"
                  >
                    <el-option
                      v-for="item in dataTypeList"
                      :key="item.id"
                      :label="item.dictKey"
                      :value="item.dictKey"
                    />
                  </el-select>
                </template>
              </el-table-column>
              <el-table-column label="操作">
                <template v-slot="{ row, $index }">
                  <el-button
                    size="small"
                    v-show="!row.isEdit"
                    @click="handleEdit(row)"
                    :disabled="tableDisabled || row.isDisable"
                    >编辑</el-button
                  >
                  <el-button
                    size="small"
                    v-show="row.isEdit"
                    :disabled="
                      (tableDisabled && !row.isEdit) ||
                      isableSave ||
                      row.name.trim() == ''
                    "
                    @click="handleSave(row)"
                    >保存</el-button
                  >
                  <el-popover
                    :visible="row.visible"
                    placement="top"
                    trigger="click"
                    :width="160"
                  >
                    <p>确定删除吗?</p>
                    <div style="margin: 0; text-align: right">
                      <el-button size="small" text @click="row.visible = false"
                        >取消</el-button
                      >
                      <el-button
                        size="small"
                        type="primary"
                        @click="handleDelete(row, $index)"
                        >确定</el-button
                      >
                    </div>
                    <template #reference>
                      <el-button
                        size="small"
                        type="danger"
                        :disabled="
                          (tableDisabled && !row.isEdit) || row.isDisable
                        "
                        @click="row.visible = true"
                      >
                        删除
                      </el-button>
                    </template>
                  </el-popover>
                </template>
              </el-table-column>
            </el-table>
          </el-form-item>
          <el-form-item>
            <el-button
              type="primary"
              @click="handleAddAttr"
              :disabled="tableDisabled"
              >添加属性</el-button
            >
          </el-form-item>
          <el-form-item
            label="默认显示属性"
            ref="defaultRef"
            prop="defaultName"
          >
            <el-select v-model="form.defaultName" :disabled="!isAdd">
              <el-option
                v-for="item in defaultNameOptions"
                :key="item.value"
                :label="item.label"
                :value="item.value"
              />
            </el-select>
          </el-form-item>
        </el-form>
      </template>
      <template #footer>
        <div style="display: flex; justify-content: center">
          <el-button
            type="primary"
            @click="confirmClick(ruleFormRef)"
            :disabled="tableDisabled"
            :loading="comfirLoading"
            >保存</el-button
          >
          <el-button @click="cancelClick">取消</el-button>
        </div>
      </template>
    </el-drawer>
  </div>
</template>

<script lang="ts" setup>
defineOptions({
  name: "topology-edit",
});
import { emitter } from "@/utils/mitt";
import type { FormRules, FormInstance } from "element-plus";
import type { Graph } from "@antv/g6";
import { ElMessage } from "element-plus";
const graphModule: Ref<Graph> = inject("graphModule");
const dataTypeList = inject("dataTypeList");
import { colorList } from "./common";
import { graphSaveApi } from "@/api/buildKg/tology";
import { deelSubmitData } from "./common/utils";
import { nodeOptions } from "./common/state";
import { getIcon, deelNode } from "./common/utils";
import G6 from "@antv/g6";

interface PropTable {
  name: string;
  dataType: string;
  isEdit?: boolean;
  code?: string;
  visible?: Boolean;
}
let currentModel;
let form = reactive({
  name: "",
  defaultName: "",
  propTable: [],
});
const defaultRef = ref();

onMounted(() => {
  emitter.on("handleTologyEdit", (currentEvt) => {
    drawer.value = true;
    currentModel = currentEvt.item.getModel();
    form.name = currentModel.labelName || "";
    iconColor.value = currentModel.style?.fill || "";
    objType.value = currentModel.objType || "1";
    isAdd.value = currentModel.isAdd || false;
    iconText.value = currentModel.icon || "";
    form.defaultName =
      currentModel.defaultNameCode || currentModel.defaultName || "";
    form.propTable = currentModel.propertyDTOList
      ? JSON.parse(JSON.stringify(currentModel.propertyDTOList))
      : [];
    nextTick(() => {
      defaultRef.value.clearValidate();
    });
  });
});

/**
 * 实体切换
 * */
let isAdd = ref(false);
let objType = ref("1");
const handleTypeChange = (ev) => {
  let label = ev.target.value;
  form.defaultName = "";
  //表示是事件
  if (label === "2") {
    form.propTable.unshift({
      name: "事发时间",
      dataType: "datetime",
      isDisable: isAdd.value,
    });
  } else {
    form.propTable.shift();
  }
  nextTick(() => {
    defaultRef.value.clearValidate();
  });
};
const tableRowClassName = ({ row }) => {
  if (row.isDisable) {
    return "disable-row";
  }
};

/**
 * 图标相关
 * */
let iconColor = ref("");
let iconText = ref("");
let isMore = ref(false);
const realIconList = computed(() => {
  return isMore.value ? iconMoreList : iconList;
});
let iconList = [
  "icon_folder_fill",
  "icon_bulb_fill",
  "icon_thunderbolt_fill",
  "icon_experiment_fill",
  "icon_flag_fill",
  "icon_alert_fill",
  "icon_fire_fill",
  "icon_shopping_fill",
  "icon_read_fill",
  "icon_gugan_fill",
];
let iconMoreList = [
  "icon_folder_fill",
  "icon_bulb_fill",
  "icon_thunderbolt_fill",
  "icon_experiment_fill",
  "icon_flag_fill",
  "icon_alert_fill",
  "icon_fire_fill",
  "icon_shopping_fill",
  "icon_read_fill",
  "icon_gugan_fill",
  "icon_qunti_fill",
  "icon_lujing_fill",
  "icon_qinmidu_fill",
  "icon_gongtonglinju_fill",
  "icon_guanxijinmidu_fill",
  "icon_weizhi_fill",
  "icon_leian_fill",
  "icon_layout_fill",
  "icon_operate_fill",
];
const showMoreIcon = () => {
  isMore.value = !isMore.value;
};
const handleColorChoose = (circleColor) => {
  iconColor.value = circleColor;
};
const handleIconChoose = (icon) => {
  iconText.value = icon;
};
const handleClearIcon = () => {
  iconText.value = "";
};

/** 表单相关*/
const isableSave = ref(false);
const checkEntName = (rule: any, value: any, callback: any) => {
  let reg = /^[\u4E00-\u9FA5a-zA-Z0-9_]{1,63}$/;
  if (value === "") {
    callback(new Error("名称不能为空"));
  } else if (!reg.test(value)) {
    callback(
      new Error(
        "对象名称只能由大小写字母、数字、中文、下划线组成，长度为1-63位"
      )
    );
  } else {
    callback();
  }
};
const checkName = (rule: any, value: any, callback: any) => {
  let nameReg = /^(?![_$])/;
  let validReg = /^[\u4E00-\u9FA5a-zA-Z0-9_]{1,63}$/;
  if (value.trim() === "") {
    isableSave.value = true;
    callback(new Error("属性不能为空"));
  } else if (!nameReg.test(value)) {
    callback(new Error("属性名不能以$和下划线开头"));
  } else if (!validReg.test(value)) {
    callback(
      new Error(
        "属性名称只能由大小写字母、数字、中文、下划线组成，长度为1-63位"
      )
    );
  } else {
    let vaildArr = form.propTable.slice(0, form.propTable.length - 1);
    let falg = false;
    vaildArr.forEach((item) => {
      if (item.name.trim() === value.trim()) {
        falg = true;
      }
    });
    if (falg) {
      isableSave.value = true;
      callback(new Error("属性不能重复"));
    } else {
      isableSave.value = false;
      callback();
    }
  }
};

const ruleFormRef = ref<FormInstance>();
const rules = reactive<FormRules>({
  name: [{ required: true, trigger: "blur", validator: checkEntName }],
  defaultName: [
    {
      required: true,
      message: "默认属性不能为空",
      trigger: "change",
    },
  ],
});

const defaultNameOptions = computed(() => {
  let defaultArr = [
    {
      label: "唯一标识",
      value: "_vid",
    },
  ];

  form.propTable.forEach((item) => {
    defaultArr.push({
      label: item.name,
      value: item.code ? item.code : item.name,
    });
  });

  return defaultArr;
});
let layout = ref("");
emitter.on("graphLayoutActive", (type) => {
  layout.value = type;
});
let comfirLoading = ref(false);
const confirmClick = async (formEl: FormInstance | undefined) => {
  if (!formEl) return;
  await formEl.validate(async (valid, fields) => {
    if (valid) {
      currentModel.propertyDTOList = form.propTable;
      currentModel.label = form.name;
      currentModel.labelName = form.name;
      currentModel.style = {
        fill: iconColor.value,
      };
      //节点文字样式
      currentModel.labelCfg = {
        style: {
          fill: iconColor.value,
        },
        position: "bottom",
      };
      currentModel.icon = iconText.value;
      currentModel.objType = objType.value;
      currentModel.defaultName = form.defaultName;
      currentModel.stateStyles = nodeOptions({
        backgroundColor: iconColor.value,
      });
      if (iconText.value) {
        currentModel.type = "iconfont";
        currentModel.text = getIcon(iconText.value);
      }
      //保存时，重置当前节点为不可编辑实体和事件
      currentModel.isAdd = false;
      let graphData = graphModule.value.save();
      let graphDeelData = deelSubmitData(graphData, layout.value);
      comfirLoading.value = true;
      let res = await graphSaveApi(graphDeelData).catch(() => {
        comfirLoading.value = false;
      });
      if (res.code === 200) {
        let renderData = res.data as Record<string, any>;
        deelNode(renderData);
        renderData?.edges && G6.Util.processParallelEdges(renderData.edges);
        graphModule.value.data(renderData);
        graphModule.value.render();
        ElMessage.success("保存成功");
        reset();
        comfirLoading.value = false;
      }
    } else {
      console.log("error submit!", fields);
    }
  });
};

/** 表格相关*/

//新增数据
const editTable = ref();
const handleAddAttr = () => {
  form.propTable.push({
    name: "",
    dataType: "string",
    isEdit: true,
  });
  nextTick(() => {
    let ScrollTop = 56.5 * form.propTable.length;
    editTable.value.setScrollTop(ScrollTop);
  });
};
const handleEdit = (row: PropTable) => {
  row.isEdit = true;
};
const handleSave = (row: PropTable) => {
  row.isEdit = false;
};
const handleDelete = (row: PropTable, index: number) => {
  if (!isAdd.value && row.code && row.code === form.defaultName) {
    ElMessage.warning("该属性已设置为默认显示属性，无法删除");
    row.visible = false;
    return;
  }
  row.visible = false;
  form.propTable.splice(index, 1);
  if (row.code && row.code === form.defaultName) {
    form.defaultName = "";
    setTimeout(() => {
      defaultRef.value.clearValidate();
    });
  } else if (row.name === form.defaultName) {
    form.defaultName = "";
    setTimeout(() => {
      defaultRef.value.clearValidate();
    });
  }
};

let tableDisabled = computed(() => {
  return !!form.propTable.filter((item) => item.isEdit)?.length;
});
//抽屉相关
let drawer = ref(false);
function cancelClick() {
  reset();
}
const reset = () => {
  form.propTable = [];
  form.name = "";
  iconColor.value = "";
  iconText.value = "";
  objType.value = "1";
  form.defaultName = "";
  drawer.value = false;
};

onUnmounted(() => {
  emitter.off("handleTologyEdit");
  emitter.off("graphLayoutActive");
});
</script>

<style scoped lang="scss">
.iconBox {
  width: 100%;

  .left-chooice {
    float: left;
    width: 64px;
    height: inherit;
    text-align: center;
    border: 1px solid #adb0b8;

    &::before {
      display: inline-block;
      height: 100%;
      vertical-align: middle;
      content: "";
    }

    .show-selection {
      display: inline-block;
      width: 30px;
      height: 30px;
      line-height: 30px;
      color: #fff;
      vertical-align: middle;
      border-radius: 50%;
    }
  }

  .right {
    margin-left: 64px;

    .up-color {
      width: 100%;
      height: 36px;
      padding: 6px 12px;
      border: 1px solid #adb0b8;
      border-left: none;

      .circle.activate {
        cursor: pointer;
        border: 2px solid #5e7ce0;
      }

      .circle {
        display: inline-block;
        width: 22px;
        height: 22px;
        margin: 0 3px;
        text-align: center;
        border: 2px solid #fff;
        border-radius: 50%;

        &:hover {
          cursor: pointer;
          border: 2px solid #5e7ce0;
        }

        .color {
          position: relative;
          top: -5px;
          display: inline-block;
          width: 14px;
          height: 14px;
          border-radius: 50%;
        }
      }
    }

    .down-icon {
      position: relative;
      width: 100%;
      padding-top: 3px;
      padding-right: 60px;
      padding-left: 12px;
      text-align: left;
      border: 1px solid #adb0b8;
      border-top: none;
      border-left: none;

      .wrapper {
        display: inline-block;
        width: 22px;
        height: 22px;
        margin: 0 3px;
        cursor: pointer;
        border-radius: 50%;

        .iconfont {
          font-size: 20px;
        }
      }

      .wrapper.activate {
        color: #1a33e6;
      }

      .collapseIcon {
        position: absolute;
        top: 4px;
        right: 100px;
        font-size: 12px;
        line-height: 18px;
        text-align: center;
        cursor: pointer;
        background-color: rgb(94 124 224 / 10%);
        border-radius: 12px;
      }
    }
  }
}

.topologyLineEdit {
  ::v-deep .el-drawer {
    .el-table {
      .cell {
        padding-bottom: 14px;
        overflow: visible;
      }

      .disable-row {
        color: #ccc;
        cursor: not-allowed;
      }

      .el-form-item {
        .el-form-item__error {
          overflow: visible;
          white-space: nowrap;
        }
      }
    }

    .el-table--enable-row-hover .el-table__body tr:hover > td.el-table__cell {
      background-color: transparent;
    }
  }
}
</style>
